﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace 现成等待与互相通知
{
    /**
        把Main方法中的线程称为主线程，把另一个线程称为工作线程，2个线程是这样工作的：
        →主线程使用WaitOne方法第一次等待，说：“工作线程，我等在这里”
        →工作线程使用Set方法，说：“主线程，我给你信号，你准备第一条信息吧”，并且又使用WaitOne方法让自己等待，就说：“主线程，我给你信号了，我等在这里，准备接收你的第一条信息”，再看看暂时还没有需要显示的信息，于是作罢
        →主线程收到工作线程的信号，设置第一条信息，然后使用Set方法，说"工作线程，我的第一条信息给你，给你信号"，并且又使用WaitOne方法让自己第二次等待，说："工作线程，我给你信号了，我等在这里"
        →工作线程又使用Set方法，说：“主线程，我给你信号，你去准备第二条信息吧”，并且又使用WaitOne方法让自己等待，就说：“主线程，我已经给你信号了，我等在这里，准备接收你的第二条信息”，再看看这时有需要显示的信息，就把信息打印了出来
        →依次类推
    **/
    class Program
    {
        static EventWaitHandle _ready = new AutoResetEvent(false);
        static EventWaitHandle _go = new AutoResetEvent(false);
        static readonly object o = new object();
        private static string _msg;
        static void Main(string[] args)
        {
            new Thread(DoSth).Start();
            //第一次等待直到另外一个线程准备好
            _ready.WaitOne();  //等待通知
            lock (o)
            {
                _msg = "你好";
            }
            _go.Set();  //表示发出信号给等待线程
            //第二次等待
            _ready.WaitOne();
            lock (o)
            {
                _msg = "吗";
            }
            _go.Set();
            //第三次
            _ready.WaitOne();
            lock (o)
            {
                _msg = null;
            }
            _go.Set();

            Console.ReadKey();
        }

        static void DoSth()
        {
            while (true)
            {
                _ready.Set();
                _go.WaitOne();
                lock (o)
                {
                    if (_msg == null) return;
                    Console.WriteLine(_msg);
                }
            }

        }

    }
    }
